/*
1.路径解析：::
2.方法调用和字段访问：., .(), []
3.函数调用和构造器：(), {}
4.一元运算符：
? (错误传播)
! (宏调用)
- (负号)
* (解引用)
& 和 &mut (引用)
! (逻辑非)
5.类型转换：as
6.乘除取模：*, /, %
7.加减：+, -
8.位移：<<, >>
9.按位与：&
10.按位异或：^
11.按位或：|
12.比较：
==, !=
<, >, <=, >=
13.逻辑与：&&
14.逻辑或：||
15.范围：.., ..=
16.赋值和复合赋值：
=
+=, -=, *=, /=, %=
&=, |=, ^=, <<=, >>=
17.闭包：|...| ...
*/

// Option 是 Rust 中处理可能存在或不存在的值的核心枚举类型，而 Some 是 Option 的一个变体。
/*
pub enum Option<T> {
    None,    // 表示无值
    Some(T), // 表示有值，值为T类型
}
*/

fn main() {
    {
        let a = String::from("mystr");
        println!("[{},{}]a={:p},{:p},{}", file!(), line!(), &a, a.as_ptr(), a);
        println!("[{},{}]size={}", file!(), line!(), calc_str_len(&a));// 调用时用&a
        println!("[{},{}]a={:p},{:p},{}", file!(), line!(), &a, a.as_ptr(), a);
    }
    {
        let mut a = String::from("mystr");
        println!("[{},{}]a={:p},{:p},{}", file!(), line!(), &a, a.as_ptr(), a);
        // 说明mut变量可以赋值到常量？
        println!("[{},{}]size={}", file!(), line!(), calc_str_len(&a));// 调用时用&a
        str_cat_fix(&mut a);
        println!("[{},{}]a={:p},{:p},{}", file!(), line!(), &a, a.as_ptr(), a);
    }
    {
        // mut变量不能同时支持多个借用。
        let mut a = String::from("hello");
        println!("[{},{}]a={:p},{:p},{}", file!(), line!(), &a, a.as_ptr(), a);
        {// 把这个作用域{}屏蔽，会报错。
            let r1 = &mut a;
            println!("[{},{}]r1={:p},{:p},{}", file!(), line!(), &r1, r1.as_ptr(), r1);
        }
        let r2 = &mut a;
        // a.push_str(",adda");// 调用失败。此时a没有修改权？
        r2.push_str(",addr2");
        println!("[{},{}]r2={:p},{:p},{}", file!(), line!(), &r2, r2.as_ptr(), r2);
        println!("[{},{}]a={:p},{:p},{}", file!(), line!(), &a, a.as_ptr(), a);// a有阅读权。
        // 常量引用可以同时支持多个。
        let r3 = &a;
        println!("[{},{}]r3={:p},{:p},{}", file!(), line!(), &r3, r3.as_ptr(), r3);
        let r4 = &a;
        println!("[{},{}]r4={:p},{:p},{}", file!(), line!(), &r4, r4.as_ptr(), r4);

    }
    {
        let mut tmpv1 = 12;
        println!("[{},{}]v1={:p}{}", file!(), line!(), &tmpv1, tmpv1);
        let tmpv2 = &mut tmpv1;// 基础类型借用后，所有者也不能使用tmpv1
        *tmpv2 = 1;
        // println!("[{},{}]v1={:p},{};v2={:p}{}", file!(), line!(), &tmpv1, tmpv1, &tmpv2, tmpv2);
        println!("[{},{}]v2={:p}{}", file!(), line!(), &tmpv2, tmpv2);
    }
}
// 引用参考
fn calc_str_len(ival : &String) -> usize {
    // 这是借用，没有所有权，仅有使用权？
    // &ival与&a的地址不同，说明他们不属于同一空间。和c++的引用有点差异？
    // 但他们保存的String字符串地址一致，说明2个地址指向同一内存？
    println!("[{},{}]val={:p},{:p},{}", file!(), line!(), &ival, ival.as_ptr(), ival);
    // ival.push_str(",addstr");//无法修改，没有mut修饰，属于常量？
    ival.len()
}

fn str_cat_fix(ival : &mut String) -> usize {
    // 这是借用，没有所有权，仅有使用权？
    // &ival与&a的地址不同，说明他们不属于同一空间。和c++的引用有点差异？
    // 但他们保存的String字符串地址一致，说明2个地址指向同一内存？
    ival.push_str(",addstr");//无法修改，没有mut修饰，属于常量？
    println!("[{},{}]val={:p},{:p},{}", file!(), line!(), &ival, ival.as_ptr(), ival);
    ival.len()
}

// fn str_new_chk_err() -> &String {
//     let s = String::from("hello");
//     &s
// }

// fn str_new_chk_err() -> &'static String {
//     let 'static s = String::from("hello");
//     &s
// }